﻿using Models;
using NLog;
using FreeSqlDemo.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using FreeSql.Aop;
using Newtonsoft.Json;

namespace FreeSqlDemo
{
    public partial class Form1 : Form
    {
        #region 变量
        private Logger _log = NLog.LogManager.GetCurrentClassLogger();
        private IFreeSql _db;
        private int _count = 100000;
        private bool _printSql = false;
        #endregion

        #region Form1
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            _db = FreeSqlUtil.CreateFreeSqlClient();
            _db.Aop.CurdAfter += CurdAfter;

            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region Log
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "\r\n\r\n";

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        textBox1.AppendText(msg);
                    }));
                }
                else
                {
                    textBox1.AppendText(msg);
                }
            }
        }
        #endregion

        #region 清空输出框
        private void button10_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
        }
        #endregion

        #region RunTask
        private Task RunTask(Action action)
        {
            return Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    Log(ex.Message + "\r\n" + ex.StackTrace);
                }
            });
        }

        private Task RunTask<T>(Action<T> action, T t)
        {
            return Task.Factory.StartNew(obj =>
            {
                try
                {
                    action((T)obj);
                }
                catch (Exception ex)
                {
                    Log(ex.Message + "\r\n" + ex.StackTrace);
                }
            }, t);
        }
        #endregion

        #region 打印SQL
        private void CurdAfter(object sender, CurdAfterEventArgs e)
        {
            if (_printSql)
            {
                RunTask(() =>
                {
                    string msg = "SQL：" + e.Sql + "\r\nParam：" + JsonConvert.SerializeObject(e.DbParms.ToDictionary(it => it.ParameterName, it => it.Value));
                    Console.WriteLine(msg);
                    _log.Debug(msg);
                });
            }
        }
        #endregion

        #region cbxPrintSql_Click
        private void cbxPrintSql_Click(object sender, EventArgs e)
        {
            _printSql = cbxPrintSql.Checked;
        }
        #endregion

        #region 生成实体类
        private void button1_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("开始生成实体类");
                Log("生成实体类完成");
            });
        }
        #endregion

        #region 测试查询
        private void button2_Click(object sender, EventArgs e)
        {
            Log("开始查询");
            SysUser conditionModel = new SysUser();
            conditionModel.Remark = "管理员";
            string remark = "管理员";
            List<SysUser> list = _db.Queryable<SysUser>().Where(t => t.Id < 20 && t.Remark.Contains(conditionModel.Remark) && t.CreateTime > new DateTime(2010, 1, 1)).ToList();
            foreach (SysUser user in list)
            {
                Log(string.Format("{0}，{1}，{2}，{3}", user.UserName, user.RealName, user.Remark, user.CreateTime.ToString("yyyy-MM-dd")));
            }
            Log("查询结束 count=" + list.Count);
        }
        #endregion

        #region 测试批量修改
        private void button3_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Random rnd = new Random();
                List<SysUser> userList = _db.Queryable<SysUser>().Where(t => t.Id > 20).ToList();
                Log("批量修改 开始 count=" + userList.Count.ToString("0 000"));
                foreach (SysUser user in userList)
                {
                    user.Remark = "测试修改用户" + rnd.Next(0, 10000);
                    user.UpdateUserid = "1";
                    user.UpdateTime = DateTime.Now;
                }

                DateTime dt = DateTime.Now;

                _db.Ado.Transaction(() =>
                {
                    _db.Update<SysUser>().SetSource(userList).ExecuteAffrows();
                });

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量修改 完成，耗时：" + time + "秒");
            });
        }
        #endregion

        #region 测试批量添加
        private void button4_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List<SysUser> userList = new List<SysUser>();
                for (int i = 1; i <= _count; i++)
                {
                    SysUser user = new SysUser();
                    user.UserName = "testUser";
                    user.RealName = "测试插入用户";
                    user.Password = "123456";
                    user.CreateUserid = "1";
                    userList.Add(user);
                }

                Log("批量添加 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;

                _db.Insert(userList).ExecuteAffrows();

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("批量添加 结束，完成：" + time + "秒");
            });
        }
        #endregion

        #region 删除
        private void button5_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Log("删除 开始");
                _db.Delete<SysUser>().Where(t => t.Id > 20).ExecuteAffrows();
                Log("删除 完成");
            });
        }
        #endregion

        #region 测试循环修改
        private void button7_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                Random rnd = new Random();
                List<SysUser> userList = _db.Queryable<SysUser>().Where(t => t.Id > 20).ToList();
                Log("循环修改 开始 count=" + userList.Count.ToString("0 000"));

                DateTime dt = DateTime.Now;

                _db.Ado.Transaction(() =>
                {
                    var repo = _db.GetRepository<SysUser>();

                    foreach (SysUser user in userList)
                    {
                        repo.Attach(user);
                    }

                    foreach (SysUser user in userList)
                    {
                        user.Remark = "测试修改用户" + rnd.Next(0, 10000);
                        user.UpdateUserid = "1";
                        user.UpdateTime = DateTime.Now;
                    }

                    foreach (SysUser user in userList)
                    {
                        repo.Update(user);
                    }
                });

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环修改 完成，耗时：" + time + "秒");
            });
        }
        #endregion

        #region 测试循环添加
        private void button6_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                List<SysUser> userList = new List<SysUser>();
                for (int i = 1; i <= _count; i++)
                {
                    SysUser user = new SysUser();
                    user.UserName = "testUser";
                    user.RealName = "测试插入用户";
                    user.Password = "123456";
                    user.CreateUserid = "1";
                    userList.Add(user);
                }

                Log("循环添加 开始 count=" + userList.Count);
                DateTime dt = DateTime.Now;


                foreach (SysUser user in userList)
                {
                    _db.Insert(user).ExecuteIdentity();
                }


                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("循环添加 完成，耗时：" + time + "秒");
            });
        }
        #endregion

        #region 查询
        private void button9_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                _db.Queryable<SysUser>().Where(t => t.Id == 1).ToList(); //预热

                Log("查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i < 10; i++)
                {
                    List<SysUser> userList = _db.Queryable<SysUser>().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderByDescending(t => t.CreateTime).OrderBy(t => t.Id).ToList();
                    Log("查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成，耗时：" + time + "秒");
            });
        }
        #endregion

        #region 分页查询
        private void button8_Click(object sender, EventArgs e)
        {
            RunTask(() =>
            {
                _db.Queryable<SysUser>().Where(t => t.Id == 1).ToList(); //预热

                Log("分页查询 开始");
                DateTime dt = DateTime.Now;

                for (int i = 0; i < 10; i++)
                {
                    long total = _db.Queryable<SysUser>().Count();
                    int pageSize = 100;
                    int pageCount = (int)((total - 1) / pageSize + 1);
                    List<SysUser> userList = new List<SysUser>();
                    for (int page = 1; page <= pageCount; page++)
                    {
                        userList.AddRange(_db.Queryable<SysUser>().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderByDescending(t => t.CreateTime).OrderBy(t => t.Id).Page(page, pageSize).ToList());
                    }
                    Log("分页查询结果 count=" + userList.Count.ToString());
                }

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("分页查询 完成，耗时：" + time + "秒");
            });
        }
        #endregion

        #region 并发查询
        private void button11_Click(object sender, EventArgs e)
        {
            string sql = _db.Select<BsOrder, BsOrderDetail>()
                .LeftJoin((o, t) => o.Id == t.OrderId)
                .GroupBy((o, t) =>
                    new
                    {
                        id = o.Id,
                        time = o.OrderTime,
                        reamark = o.Remark
                    })
                .OrderByDescending(t => t.Sum(t.Value.Item2.Price * t.Value.Item2.Quantity))
                .ToSql((t) =>
                    new
                    {
                        total = t.Sum(t.Value.Item2.Price * t.Value.Item2.Quantity),
                        id = t.Value.Item1.Id,
                        time = t.Value.Item1.OrderTime,
                        remark = t.Value.Item1.Remark
                    });
            Log(sql);

            return;


            RunTask(() =>
            {
                Log("查询 开始");
                DateTime dt = DateTime.Now;

                List<Task> tasks = new List<Task>();
                for (int i = 0; i < 200; i++)
                {
                    Task task = RunTask(() =>
                    {
                        List<SysUser> userList = _db.Queryable<SysUser>().Where(t => t.Id > 20 && t.RealName.Contains("测试")).OrderByDescending(t => t.CreateTime).OrderBy(t => t.Id).ToList();
                        Log("查询结果 count=" + userList.Count.ToString());
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());

                string time = DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000");
                Log("查询 完成，耗时：" + time + "秒");
            });
        }
        #endregion

    }
}
